#pragma once
#include <boost/algorithm/string.hpp>
#include <vector>
#include <jsoncpp/json/json.h>
#include <random>
#include "manager.hpp"
#include "cpp-httplib/httplib.h"
#include "MyAlgorithm.hpp"
#define PSW_WRONG 4 // 密码错误
#define SUCCESS 5   // 登录成功

class UpdateUtil
{
public:
    // 从mysql中加载数据到redis
    static void LoadUserDate(std::string &output)
    {
        Manager *manager = Manager::GetInstance();
        Data result; // 取出数据
        int status = manager->GetUserData(result);
        Json::Value root;
        Json::Value info(Json::arrayValue);
        // 数据存在
        if (status == EXIST)
        {
            root["status"] = "EXIST";
            redisContext *redis_conn = redisConnect(LOCAL_HOST, 6379);
            std::string hash_key = "userdata";
            for (auto &item : result)
            {
                Json::Value elem;
                elem["name"] = item[0].second;
                elem["addr"] = item[1].second;
                elem["tele"] = item[2].second;
                elem["login"] = item[3].second;
                info.append(elem);
                Json::FastWriter writer;
                redisReply *reply = (redisReply *)redisCommand(redis_conn, "sadd %s %s", hash_key.c_str(), writer.write(elem).c_str());
                if (reply == nullptr || reply->type == REDIS_REPLY_ERROR)
                {
                    LOGERR("sadd UserData err");
                }
            }
        }
        else
        {
            root["status"] = "NOEXIST";
            LOGERR("Get UserDara err");
        }
        root["info"] = info;
        Json::FastWriter writer;
        output = writer.write(root);
        LOG(DEBUG,output);
    }
};

class LogUtil
{
public:
    static int Log(const httplib::Params &params)
    {
        std::string name = params.find("username")->second;
        std::string pass = params.find("password")->second;
        // 连接redis
        redisContext *redis_conn = redisConnect("localhost", 6379);
        // redisReply *reply = (redisReply *)redisCommand(redis_conn, "HMSET %s name %s addr %s tele %s login %s");
        std::string hash_key = name;
        // 从Redis中获取数据
        redisReply *reply = (redisReply *)redisCommand(redis_conn, "GET %s", hash_key.c_str());

        if (reply->type == REDIS_REPLY_STRING)
        {
            const char *password = reply->str;
            if (strcmp(password, pass.c_str()) == 0)
            {
                return SUCCESS;
            }
            else
            {
                return PSW_WRONG;
            }
        }
        else if (reply->type == REDIS_REPLY_NIL || reply->type == REDIS_REPLY_ERROR)
        {
            return NOEXIST;
        }
        else
        {
            return SQLERROR;
        }
    }
};

class DataUtil
{
public:
    // 获取业主列表
    static void GetUserData(std::string &output)
    {
        redisContext *redis_conn = redisConnect(LOCAL_HOST, 6379);
        const std::string hash_key = "userdata";
        redisReply *reply = (redisReply *)redisCommand(redis_conn, "smembers %s", hash_key.c_str());
        if (reply->elements != 0)
        {
            Json::Value root;
            Json::Value info(Json::arrayValue);
            root["status"] = "EXIST";
            for (int i = 0; i < reply->elements; i++)
            {
                Json::Reader reader;
                Json::Value elem;
                reader.parse(((redisReply *)(reply->element[i]))->str,elem);
                info.append(elem);
            }
            root["info"] = info;
            Json::FastWriter writer;
            output = writer.write(root);
        }
        else if (reply->elements == 0)
        {
            UpdateUtil::LoadUserDate(output);
        }
    }

    // 删除业主信息
    static int DelUserData(const httplib::Params &params)
    {
        std::string addr;
        auto iter = params.find("upid");
        if (iter != params.end())
        {
            addr = iter->second;
        }
        else
        {
            addr = params.find("addr")->second;
        }
        // const std::string addr = params.find("word")->second;
        Manager *manager = Manager::GetInstance();
        if (manager->DelUserData(addr))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }

    // 添加业主
    static int AddUserData(const httplib::Params &params)
    {
        std::vector<std::string> info;
        const std::string name = params.find("name")->second;
        const std::string addr = params.find("addr")->second;
        const std::string tele = params.find("tele")->second;
        const std::string login = params.find("login")->second;
        info.emplace_back(std::move(name));
        info.emplace_back(std::move(addr));
        info.emplace_back(std::move(tele));
        info.emplace_back(std::move(login));

        Manager *manager = Manager::GetInstance();
        if (manager->AddUserData(info))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }
    // 修改业主信息
    static int UpUserData(const httplib::Params &params)
    {
        // 删除用户后再插入
        if (DelUserData(params) == SUCCESS)
        {
            if (AddUserData(params) == SUCCESS)
            {
                return SUCCESS;
            }
        }
        else
        {
            return SQLERROR;
        }
    }
    // 业主缴费清单
    static int GetPayList(std::string &output)
    {
        Manager *manager = Manager::GetInstance();
        Data result;
        int ret;
        int status = manager->GetPayList(result);
        Json::Value root;
        Json::Value info(Json::arrayValue);
        // 数据存在
        if (status == EXIST)
        {
            root["status"] = "EXIST";
            for (auto &item : result)
            {
                Json::Value elem;
                elem["id"] = item[0].second;
                elem["addr"] = item[1].second;
                elem["type"] = item[2].second;
                elem["amount"] = item[3].second;
                elem["cdate"] = item[4].second;
                info.append(elem);
            }
            root["status"] = "EXIST";
            ret = EXIST;
        }
        else if (status == NOEXIST)
        {
            root["status"] = "NOEXIST";
            ret = NOEXIST;
        }
        else
        {
            root["status"] == "SQLERROR";
            ret = SQLERROR;
        }
        Json::FastWriter writer;
        root["info"] = info;
        output = writer.write(root);

        return ret;
    }

    // 添加缴费
    static int AddPayData(const httplib::Params &params)
    {
        std::vector<std::string> info;
        std::string id;
        generateOrderNumber(id);
        const std::string addr = params.find("addr")->second;
        const std::string type = params.find("type")->second;
        const std::string amount = params.find("amount")->second;
        const std::string cdate = params.find("cdate")->second;
        info.emplace_back(std::move(id));
        info.emplace_back(std::move(addr));
        info.emplace_back(std::move(type));
        info.emplace_back(std::move(amount));
        info.emplace_back(std::move(cdate));

        Manager *manager = Manager::GetInstance();
        if (manager->AddPayData(info))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }

    // 删除缴费
    static int DelPayData(const httplib::Params &params)
    {
        std::string id = params.find("id")->second;
        // const std::string addr = params.find("word")->second;
        Manager *manager = Manager::GetInstance();
        if (manager->DelPayData(id))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }

    // 获得报修列表
    static int GetRepairList(std::string &output)
    {
        Manager *manager = Manager::GetInstance();
        Data result;
        int ret;
        int status = manager->GetRepairList(result);
        Json::Value root;
        Json::Value info(Json::arrayValue);
        // 数据存在
        if (status == EXIST)
        {
            root["status"] = "EXIST";
            for (auto &item : result)
            {
                Json::Value elem;
                elem["id"] = item[0].second;
                elem["addr"] = item[1].second;
                elem["thing"] = item[2].second;
                elem["fee"] = item[3].second;
                elem["cdate"] = item[4].second;
                info.append(elem);
            }
            root["status"] = "EXIST";
            ret = EXIST;
        }
        else if (status == NOEXIST)
        {
            root["status"] = "NOEXIST";
            ret = NOEXIST;
        }
        else
        {
            root["status"] == "SQLERROR";
            ret = SQLERROR;
        }
        Json::FastWriter writer;
        root["info"] = info;
        output = writer.write(root);

        return ret;
    }

    // 获得规划列表
    static int PlanList(std::string &output)
    {
        Manager *manager = Manager::GetInstance();
        Data Info;
        int ret;
        int status = manager->GetRepairList(Info);
        Json::Value root;
        Json::Value info(Json::arrayValue);
        // 数据存在
        if (status == EXIST)
        {
            Data result;
            Handler h;
            h.getTaskList(Info, result, 3);
            root["status"] = "EXIST";
            for (auto &item : result)
            {
                Json::Value elem;
                elem["id"] = item[0].second;
                elem["addr"] = item[1].second;
                elem["thing"] = item[2].second;
                elem["fee"] = item[3].second;
                elem["cdate"] = item[4].second;
                elem["workerId"] = item[5].second;
                info.append(elem);
            }
            root["status"] = "EXIST";
            ret = EXIST;
        }
        else if (status == NOEXIST)
        {
            root["status"] = "NOEXIST";
            ret = NOEXIST;
        }
        else
        {
            root["status"] == "SQLERROR";
            ret = SQLERROR;
        }
        Json::FastWriter writer;
        root["info"] = info;
        output = writer.write(root);

        return ret;
    }

    // 删除报修
    static int DelRepairData(const httplib::Params &params)
    {
        std::string id = params.find("id")->second;
        Manager *manager = Manager::GetInstance();
        if (manager->DelRepairData(id))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }

    // 添加报修
    static int AddRepairData(const httplib::Params &params)
    {
        std::vector<std::string> info;
        std::string id;
        generateOrderNumber(id);
        const std::string addr = params.find("addr")->second;
        const std::string thing = params.find("thing")->second;
        const std::string fee = params.find("fee")->second;
        const std::string cdate = params.find("cdate")->second;
        info.emplace_back(std::move(id));
        info.emplace_back(std::move(addr));
        info.emplace_back(std::move(thing));
        info.emplace_back(std::move(fee));
        info.emplace_back(std::move(cdate));

        Manager *manager = Manager::GetInstance();
        if (manager->AddRepairData(info))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }

    static int AddUser(const httplib::Params &params)
    {
        int status = 0;
        std::string name = params.find("username")->second;
        std::string pass = params.find("password")->second;
        std::string login = params.find("login")->second;

        // 连接redis
        redisContext *redis_conn = redisConnect("localhost", 6379);
        std::string hash_key = name;
        // 从Redis中获取数据
        redisReply *reply = (redisReply *)redisCommand(redis_conn, "GET %s", hash_key.c_str());

        if (reply->type == REDIS_REPLY_STRING)
        {
            status = EXIST;
        }
        else if (reply->type == REDIS_REPLY_NIL)
        {
            reply = (redisReply *)redisCommand(redis_conn, "SET %s %s", name.c_str(), pass.c_str());
            if (reply->type == REDIS_REPLY_STATUS)
            {
                status = SUCCESS;
            }
            else
            {
                status = SQLERROR;
            }
        }
        else
        {
            status = SQLERROR;
        }
        freeReplyObject(reply);
        redisFree(redis_conn);
        return status;
    }

    // 获得医疗信息列表
    static int GetMedicalList(std::string &output)
    {
        Manager *manager = Manager::GetInstance();
        Data result;
        int ret;
        int status = manager->GetMedicalList(result);
        Json::Value root;
        Json::Value info(Json::arrayValue);
        // 数据存在
        if (status == EXIST)
        {
            root["status"] = "EXIST";
            for (auto &item : result)
            {
                Json::Value elem;
                elem["name"] = item[0].second;
                elem["addr"] = item[1].second;
                elem["tele"] = item[2].second;
                elem["ident"] = item[3].second;
                elem["medicalType"] = item[4].second;
                elem["diseaseType"] = item[5].second;
                elem["seriousType"] = item[6].second;
                info.append(elem);
            }
            root["status"] = "EXIST";
            ret = EXIST;
        }
        else if (status == NOEXIST)
        {
            root["status"] = "NOEXIST";
            ret = NOEXIST;
        }
        else
        {
            root["status"] == "SQLERROR";
            ret = SQLERROR;
        }
        Json::FastWriter writer;
        root["info"] = info;
        output = writer.write(root);

        return ret;
    }

    // 删除医疗信息
    static int DelMedicalData(const httplib::Params &params)
    {
        std::string ident = params.find("ident")->second;
        Manager *manager = Manager::GetInstance();
        if (manager->DelMedicalData(ident))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }

    // 添加医疗信息
    static int AddMedicalData(const httplib::Params &params)
    {
        std::vector<std::string> info;
        const std::string name = params.find("name")->second;
        const std::string addr = params.find("addr")->second;
        const std::string tele = params.find("tele")->second;
        const std::string ident = params.find("ident")->second;
        const std::string medicalType = params.find("medicalType")->second;
        const std::string diseaseType = params.find("diseaseType")->second;
        const std::string seriousType = params.find("seriousType")->second;
        info.emplace_back(std::move(name));
        info.emplace_back(std::move(addr));
        info.emplace_back(std::move(tele));
        info.emplace_back(std::move(ident));
        info.emplace_back(std::move(medicalType));
        info.emplace_back(std::move(diseaseType));
        info.emplace_back(std::move(seriousType));

        Manager *manager = Manager::GetInstance();
        if (manager->AddMedicalData(info))
        {
            return SUCCESS;
        }
        else
        {
            return SQLERROR;
        }
    }
    static void generateOrderNumber(std::string &output)
    {
        std::string orderNumber;
        const int len = 15;                            // 生成的订单号位数
        std::random_device rd;                         // 获取真随机数种子
        std::mt19937 gen(rd());                        // 初始化随机数生成器
        std::uniform_int_distribution<> distrib(0, 9); // 生成0-9之间的均匀分布整数

        // 生成随机数字字符并添加到订单号中
        for (int i = 0; i < len; ++i)
        {
            output += std::to_string(distrib(gen));
        }
    }
};
